package account;

import java.awt.Color;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Random;

/**
 * Die Modelklasse zur Verwaltung der Konten und deren Logik.
 *
 * @author Patrick Bauer
 */
public class AccountModel extends Observable{
    /**
     * Beinhaltet alle vorhandenen Kontos
     */
    private ArrayList<Account> accountList = new ArrayList<Account>();

    /**
     * Fuegt ein neues Konto der Kontoliste hinzu.<br>
     * Einem neuen Konto wird dabei ein zufaelliger Farbwert uebergeben.
     */
    public void addAccount(){
        Random random = new Random();
        
        this.accountList.add(new Account(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255))));
    }


    /**
     * Bearbeitet eine Kontoeinzahlung.<br>
     * Uebergebene Daten werden auf Fehler ueberprueft und bei Bedarf wird eine Exception geworfen.
     *
     * @param accountIndex der Index des zu bearbeitenden Kontos
     * @param diff der Geldbetrag der eingezahlt werden soll
     * @throws NumberFormatException Fehlermeldung (ungueltige Zahl, zu kleine oder zu grosse Zahlen)
     */
    public void raiseBalance(int accountIndex, String diff) throws NumberFormatException {
        float difference;
        
        diff = diff.replaceAll(",", ".");
        
        try {
            difference = Float.parseFloat(diff);
        } catch (NumberFormatException  e) {
            throw new NumberFormatException("Keine gueltige Zahl.");            
        }
        
        if (difference < (float)0.01){
            throw new NumberFormatException("Mindestens 0.01 Euro.");
        }
        
        try {
            DecimalFormat twoDForm = new DecimalFormat("#.00");
            difference = Float.valueOf(twoDForm.format(difference).replaceAll(",", "."));
        } catch (NumberFormatException e) {
            throw new NumberFormatException("Zahl zu groß.");
        }
        
        this.accountList.get(accountIndex).setBalance(this.accountList.get(accountIndex).getBalance() + difference);
        
        this.setChanged();
        this.notifyObservers(new AccountAction(accountIndex, difference, AccountAction.RAISE));
    };


    /**
     * Bearbeitet eine Kontoauszahlung.<br>
     * Uebergebene Daten werden auf Fehler ueberprueft und bei Bedarf wird eine Exception geworfen.
     *
     * @param accountIndex der Index des zu bearbeitenden Kontos
     * @param diff der Geldbetrag der ausgezahlt werden soll
     * @throws NumberFormatException Fehlermeldung (ungueltige Zahl, zu kleine oder zu grosse Zahlen, Ueberziehung des Kontos)
     */
    public void lowerBalance(int accountIndex, String diff) throws NumberFormatException {
        float difference;
        
        diff = diff.replaceAll(",", ".");
        
        try {
            difference = Float.parseFloat(diff);
        }           
        catch (NumberFormatException e) {
            throw new NumberFormatException("Keine gueltige Zahl.");            
        }
        
        if (difference < (float)0.01){
            throw new NumberFormatException("Mindestens 0.01 Euro.");
        }
        
        try {
            DecimalFormat twoDForm = new DecimalFormat("#.00");
            difference = Float.valueOf(twoDForm.format(difference).replaceAll(",", "."));
        } catch (NumberFormatException e) {
            throw new NumberFormatException("Zahl zu groß.");
        }
        
        if ((this.accountList.get(accountIndex).getBalance() - difference) < 0.0) {
            throw new NumberFormatException("Keine Ueberziehung erlaubt.");
        }
        
        this.accountList.get(accountIndex).setBalance(this.accountList.get(accountIndex).getBalance() - difference);
        
        this.setChanged();
        this.notifyObservers(new AccountAction(accountIndex, difference, AccountAction.LOWER));
    };
    
    /**
     * Liefert den Kontostand des angegebenen Kontos.
     *
     * @param index Index des auszulesenden Kontos
     * @return der Kontostand
     */
    public float getBalancebyIndex(int index) {
        return this.accountList.get(index).getBalance();
    }

    /**
     * Liefert die Farbe des angebenen Kontos.
     *
     * @param index Index des auszulesenden Kontos
     * @return die Farbe
     */
    public Color getColorbyIndex(int index) {
        return this.accountList.get(index).getColor();
    }

    /**
     * Liefert die Anzahl der eingetragenen Kontos.
     *
     * @return die Anzahl der Kontos
     */
    public int getAccountCount() {
        return this.accountList.size();
    }

}
